import React, { Component } from 'react';
import { Row, Col, Table } from 'antd';
import { Chart, Tooltip, Geom, Coord, Label } from 'bizcharts';
import { DataView } from '@antv/data-set';
import Ellipsis from '@/components/Ellipsis';
import An from '@/components/An';
import ResizeObserver from 'resize-observer-polyfill';
import { themeLight, themeDark, commonConfig, pieConfig, fitFontSize, fitHeight } from '../config';
import styles from '../index.less';

const { defaultTheme, defaultFontFamily, defaultChartUnitFontSize } = commonConfig;
const {
  defaultInnerRadius,
  defaultTotalFontSize,
  defaultTitleFontSize,
  defaultTitleMarginTop,
  defaultTitleLines,
  defaultLineWidth,
  defaultLabelFontSize,
  defaultPieLegendLineHeight,
} = pieConfig;

/* eslint react/no-danger:0 */
class Pie extends Component {
  state = {
    height: 0,
    viewportScale: window.viewportScale,
  };

  componentDidMount() {
    this.resizeObserver();
    window.addEventListener('resize', this.resize, { passive: true });
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize);
  }

  getG2Instance = chart => {
    this.chart = chart;
  };

  handleRoot = n => {
    this.root = n;
  };

  resize = () => {
    this.setState({ viewportScale: window.viewportScale });
  };

  resizeObserver() {
    const ro = new ResizeObserver(entries => {
      const { height } = entries[0].contentRect;
      this.setState(preState => {
        if (preState.height !== height) {
          return {
            height,
          };
        }
        return null;
      });
    });
    if (this.chartDom) {
      ro.observe(this.chartDom);
    }
  }

  render() {
    const { height: stateHeight, viewportScale } = this.state;
    const { theme = defaultTheme } = this.props;
    const {
      defaultColors,
      defaultEmptyColor,
      defaultPercentColor,
      defaultTotalColor,
      defaultTitleColor,
      defaultSplitLineColor,
      defaultSplitLabelColor,
      defaultChartUnitColor,
      defaultLegendColor,
    } = theme === 'dark' ? themeDark : themeLight;
    const {
      style = {},
      height: propsHeight,
      forceFit = true,
      percent,
      padding = 10 * viewportScale,
      inner = defaultInnerRadius,
      geomStyle = {},
      showTooltipValue = false, // true：tooltip展示具体数值，false：tooltip展示百分比
      color,
      emptyColor = defaultEmptyColor, // 空数据图表颜色
      total,
      showTotalUnit = true, // 显示合计单位
      showLegend = false, // 是否展示图例
      showLegendValue = true, // 是否展示具体数值
      showLegendAn = true, // 是否展示同比
      legendLineHeight = defaultPieLegendLineHeight, // 图例行高
      legendFontSize,
      legendColumns, // 图例标题
      absoluteLegend = false, // 图例绝对定位
      x = 'x', // 分类字段名
      y = 'y', // value字段名
      anName = 'an', // 同比字段名
      showLabel = false, // 图形中展示百分比（实心图用）
      unit,
      totalFontSize = defaultTotalFontSize,
      title,
      titleColor = defaultTitleColor,
      titleFontSize = defaultTitleFontSize,
      titleLines = defaultTitleLines, // 限制标题行数，若无需限制传0

      xScale = {},
      yScale = {},
      pieColSpan = 12,
      an,
      anParams = {},
      showAn,
    } = this.props;

    const {
      data: propsData,
      showTooltip: propsShowTooltip = true,
      totalColor: propsTotalColor,
    } = this.props;

    let data = propsData || [];
    let showTooltip = propsShowTooltip;
    const totalColor = propsTotalColor || defaultTotalColor;
    let chartColor = color || defaultColors;
    let emptyData = false; // 查询饼图数据为空数组

    const scale = {
      [x]: {
        type: 'cat',
        range: [0, 1],
        ...xScale,
      },
      [y]: {
        min: 0,
        ...yScale,
      },
      percent: {
        formatter: val => `${(val * 100).toFixed(2)}%`,
      },
    };
    // percent !== undefined数据为0不出现图形处理
    if (percent !== undefined) {
      showTooltip = false;
      chartColor = color || defaultPercentColor;
      data = [
        {
          x: '占比',
          y: parseFloat(percent),
        },
        {
          x: '反比',
          y: 100 - parseFloat(percent),
        },
      ];
    } else if (data && !data.length) {
      showTooltip = false;
      emptyData = [
        {
          [x]: 'empty',
          [y]: 100,
        },
      ];
    } else if (data) {
      let empty = true;
      data.map(item => {
        if (Number(item[y]) > 0) empty = false;
      });
      if (empty) {
        showTooltip = false;
        emptyData = [
          {
            [x]: 'empty',
            [y]: 100,
          },
        ];
      }
    }

    const tooltip = showTooltipValue
      ? [
          `${x}*${y}`,
          (name, value) => ({
            name,
            value: value + (unit || ''),
          }),
        ]
      : [
          `${x}*percent`,
          (name, p) => ({
            name,
            value: `${(p * 100).toFixed(2)}%`,
          }),
        ];

    const dv = new DataView();
    dv.source(emptyData || data).transform({
      type: 'percent',
      field: y,
      dimension: x,
      as: 'percent',
    });

    if (legendColumns && dv.rows.length) {
      const nameColumn = legendColumns.filter(item => item.key === x)[0];
      nameColumn.render = (text, record, index) => (
        <span>
          <div className={styles.icon} style={{ background: chartColor[index % 10] }} />
          {text}
        </span>
      );
      const percentColumn = legendColumns.filter(item => item.key === 'percent')[0];
      percentColumn.render = text => (text ? `${(text * 100).toFixed(2)}%` : '0%');
      const anColumn = legendColumns.filter(item => item.key === 'an');
      if (anColumn.length) {
        anColumn[0].render = text => <An num={text} showTitle={false} />;
      }
    }

    const height = propsHeight || stateHeight;

    return (
      <div ref={this.handleRoot} className={styles.pie} style={style} key={this.root}>
        <Row>
          <Col
            span={showLegend ? pieColSpan : 24}
            style={
              data && legendLineHeight * data.length > height && !absoluteLegend
                ? { paddingTop: ((legendLineHeight * data.length - height) / 2) * viewportScale }
                : {}
            }
          >
            <div
              ref={ref => {
                this.chartDom = ref;
              }}
            >
              <div className={styles.chart}>
                <Chart
                  scale={scale}
                  height={height * viewportScale}
                  forceFit={forceFit}
                  data={dv}
                  padding={padding}
                  onGetG2Instance={this.getG2Instance}
                >
                  <div>{!!showTooltip && <Tooltip showTitle={false} />}</div>
                  <Coord type="theta" innerRadius={inner} />
                  <Geom
                    style={geomStyle}
                    tooltip={showTooltip && tooltip}
                    type="intervalStack"
                    position="percent"
                    color={emptyData ? emptyColor : [x, chartColor]}
                    select={false}
                  >
                    {/*  {showLabel && (
                      <Label
                        content="percent"
                        offset={(-height / 6) * viewportScale}
                        textStyle={{
                          textAlign: 'center',
                          fill: defaultSplitLabelColor,
                          fontSize: fitFontSize(defaultLabelFontSize),
                          fontFamily: defaultFontFamily,
                          // fontWeight: 'bold',
                          rotate: 360,
                        }}
                      />
                    )} */}
                  </Geom>
                </Chart>
                {(total !== undefined || percent !== undefined) && (
                  <div
                    style={{ color: totalColor, fontSize: totalFontSize * viewportScale }}
                    className={styles.total}
                  >
                    {total !== undefined ? total : `${percent || 0}%`}
                    {showTotalUnit && unit && percent === undefined && (
                      <div
                        style={{
                          color: defaultChartUnitColor,
                          fontSize: fitFontSize(defaultChartUnitFontSize),
                        }}
                      >
                        {unit}
                      </div>
                    )}
                  </div>
                )}
              </div>
            </div>
            {showAn && <An num={an} block {...anParams} height={fitHeight(21)} />}
            {title && (
              <div
                style={{
                  color: titleColor,
                  fontSize: titleFontSize * viewportScale,
                  marginTop: defaultTitleMarginTop,
                  height: titleLines * fitHeight(21),
                  lineHeight: `${fitHeight(21)}px`,
                }}
                className={styles.title}
              >
                <Ellipsis lines={titleLines} tooltip>
                  {title}
                </Ellipsis>
              </div>
            )}
          </Col>
          {showLegend && data && (
            <Col
              span={24 - pieColSpan}
              style={
                (legendLineHeight * data.length < height || absoluteLegend) && !legendColumns
                  ? { position: 'relative', marginTop: (height / 2) * viewportScale }
                  : {}
              }
            >
              {legendColumns ? (
                <div className={`${styles.pieTableLegend} ${theme === 'dark' ? styles.dark : ''}`}>
                  <Table
                    dataSource={emptyData ? data : dv.rows}
                    columns={legendColumns}
                    pagination={false}
                    rowKey={x}
                  />
                </div>
              ) : (
                <div
                  className={styles.pieLegend}
                  style={
                    legendLineHeight * data.length < height || absoluteLegend
                      ? {
                          marginTop: -(legendLineHeight * data.length * viewportScale) / 2,
                          position: 'absolute',
                          top: '50%',
                          color: defaultLegendColor,
                          fontSize: legendFontSize ? legendFontSize * viewportScale : '0.32rem',
                        }
                      : {
                          color: defaultLegendColor,
                          fontSize: legendFontSize ? legendFontSize * viewportScale : '0.32rem',
                        }
                  }
                >
                  {data.length > 0 &&
                    (!emptyData
                      ? dv.rows.map((item, index) => (
                          <div
                            key={index}
                            style={{
                              height: legendLineHeight * viewportScale,
                              lineHeight: `${legendLineHeight * viewportScale}px`,
                              whiteSpace: 'nowrap',
                            }}
                          >
                            <div
                              className={styles.icon}
                              style={{ background: chartColor[index % 10] }}
                            />
                            <span>{item[x]}</span>
                            {!showLabel && <span>{`${(item.percent * 100).toFixed(2)}%`}</span>}
                            {showLegendValue && (
                              <span style={{ marginLeft: '0.4rem' }}>{item[y]}</span>
                            )}
                            {showLegendValue && unit && (
                              <span style={{ marginLeft: 0 }}>{unit}</span>
                            )}
                            {showLegendAn && item[anName] !== undefined && (
                              <An num={Number(item[anName])} />
                            )}
                          </div>
                        ))
                      : data.map((item, index) => (
                          <div
                            key={index}
                            style={{
                              height: legendLineHeight * viewportScale,
                              lineHeight: `${legendLineHeight * viewportScale}px`,
                              whiteSpace: 'nowrap',
                            }}
                          >
                            <div
                              className={styles.icon}
                              style={{ background: chartColor[index % 10] }}
                            />
                            <span>{item[x]}</span>
                            {!showLabel && <span>0%</span>}
                            {showLegendValue && (
                              <span style={{ marginLeft: '0.4rem' }}>{item[y]}</span>
                            )}
                            {showLegendValue && unit && (
                              <span style={{ marginLeft: 0 }}>{unit}</span>
                            )}
                            {showLegendAn && item[anName] !== undefined && (
                              <An num={Number(item[anName])} />
                            )}
                          </div>
                        )))}
                </div>
              )}
            </Col>
          )}
        </Row>
      </div>
    );
  }
}

export default Pie;
